package redis

import (
	"errors"
	"github.com/gomodule/redigo/redis"
	"strconv"
)

// Do 扩展方法
func (p *Pool) Do(command string, args ...interface{}) (interface{}, error) {
	return p.do(command, args...)
}

// Get 注意：获取不到key时，会返回ERROR(redigo, nil returned)
func (p *Pool) Get(key string) (string, error) {
	reply, err := p.do("get", key)
	return redis.String(reply, err)
}

func (p *Pool) Set(key, value string) (string, error) {
	reply, err := p.do("set", key, value)
	return redis.String(reply, err)
}

func (p *Pool) Del(keys ...string) (int, error) {
	args := make([]interface{}, len(keys))
	for i, key := range keys {
		args[i] = key
	}
	reply, err := p.do("del", args...)
	return redis.Int(reply, err)
}

func (p *Pool) SetEx(key string, expire int, value string) (string, error) {
	reply, err := p.do("set", key, value, "ex", expire)
	return redis.String(reply, err)
}

func (p *Pool) Exists(keys ...string) (int, error) {
	args := make([]interface{}, len(keys))
	for i, key := range keys {
		args[i] = key
	}
	reply, err := p.do("exists", args...)
	return redis.Int(reply, err)
}

func (p *Pool) TTL(key string) (seconds int, err error) {
	reply, err := p.do("ttl", key)
	return redis.Int(reply, err)
}

func (p *Pool) Expire(key string, seconds int) (bool, error) {
	reply, err := p.do("expire", key, seconds)
	return redis.Bool(reply, err)
}

// SetNX 当seconds为0时，代表不需要指定过期时间
func (p *Pool) SetNX(key string, value interface{}, seconds int) (string, error) {
	var reply interface{}
	var err error
	if seconds == 0 {
		reply, err = p.do("setnx", key, value)
	} else {
		reply, err = p.do("set", key, value, "ex", seconds, "nx")
	}
	return redis.String(reply, err)
}

func (p *Pool) Incr(key string) (int, error) {
	reply, err := p.do("incr", key)
	return redis.Int(reply, err)
}

func (p *Pool) IncrBy(key string, value int) (int, error) {
	reply, err := p.do("incrby", key, value)
	return redis.Int(reply, err)
}

func (p *Pool) Decr(key string) (int, error) {
	reply, err := p.do("incr", key)
	return redis.Int(reply, err)
}

func (p *Pool) DecrBy(key string, value int) (int, error) {
	reply, err := p.do("incrby", key, value)
	return redis.Int(reply, err)
}

// MSet client.MSet([]interface{}{"test_1", "value1", "test_2", "value2"}...)
// return "OK", nil
func (p *Pool) MSet(pairs map[string]interface{}) (status string, err error) {
	var args = make([]interface{}, 0, 2*len(pairs))
	for k, v := range pairs {
		args = append(args, k, v)
	}
	reply, err := p.do("mset", args...)
	return redis.String(reply, err)
}

// MGet 返回的数据，其中interface{}为[]uint8
func (p *Pool) MGet(keys ...interface{}) ([]string, error) {
	reply, err := p.do("mget", keys...)
	if err != nil {
		return nil, err
	}
	return redis.Strings(reply, err)
}

// --------------------------------------------List-----------------------------------------------

func (p *Pool) BLPop(timeoutMS int, keys ...interface{}) ([]string, error) {
	var args = make([]interface{}, 0, len(keys)+1)
	for i := 0; i < len(keys); i++ {
		args = append(args, keys[i])
	}
	args = append(args, timeoutMS)
	reply, err := p.do("blpop", args...)
	if err != nil {
		return nil, err
	}
	res, err := redis.Strings(reply, err)

	return res, nil
}

func (p *Pool) BRPop(timeoutSeconds int, keys ...interface{}) ([]string, error) {
	var args = make([]interface{}, 0, len(keys)+1)
	for i := 0; i < len(keys); i++ {
		args = append(args, keys[i])
	}
	args = append(args, timeoutSeconds)
	reply, err := p.do("brpop", args...)
	if err != nil {
		return nil, err
	}
	res, err := redis.Strings(reply, err)

	return res, nil
}

func (p *Pool) BRPopLPush(source, dest string, timeoutSeconds int) (string, error) {
	reply, err := p.do("brpoplpush", source, dest, timeoutSeconds)
	return redis.String(reply, err)
}

// LIndex 根据下标获取列表中的元素，从0开始，-1代表最后一个元素
// interface{}为[]uint8
func (p *Pool) LIndex(key string, index int) (string, error) {
	reply, err := p.do("lindex", key, index)
	return redis.String(reply, err)
}

func (p *Pool) LInsert(key, op string, pivot, value interface{}) (int, error) {
	reply, err := p.do("linsert", key, op, pivot, value)
	return redis.Int(reply, err)
}

func (p *Pool) LInsertBefore(key string, pivot, value interface{}) (int, error) {
	reply, err := p.do("linsert", key, "before", pivot, value)
	return redis.Int(reply, err)
}

func (p *Pool) LInsertAfter(key string, pivot, value interface{}) (int, error) {
	reply, err := p.do("linsert", key, "after", pivot, value)
	return redis.Int(reply, err)
}

func (p *Pool) LLen(key string) (int, error) {
	reply, err := p.do("llen", key)
	return redis.Int(reply, err)
}

func (p *Pool) LPop(key string) (string, error) {
	reply, err := p.do("lpop", key)
	return redis.String(reply, err)
}

func (p *Pool) LPush(key string, values ...interface{}) (int, error) {
	args := make([]interface{}, 1+len(values))
	args[0] = key
	for i := 0; i < len(values); i++ {
		args[i+1] = values[i]
	}
	reply, err := p.do("lpush", args...)
	return redis.Int(reply, err)
}

// LPushX 只有列表存在时才会插入
func (p *Pool) LPushX(key string, value interface{}) (int, error) {
	reply, err := p.do("lpushx", key, value)
	return redis.Int(reply, err)
}

func (p *Pool) LRange(key string, start, stop int) ([]string, error) {
	reply, err := p.do("lrange", key, start, stop)
	return redis.Strings(reply, err)
}

func (p *Pool) LRem(key string, count int, value interface{}) (int, error) {
	reply, err := p.do("lrem", key, count, value)
	return redis.Int(reply, err)
}

func (p *Pool) LSet(key string, index int, value interface{}) (string, error) {
	reply, err := p.do("lset", key, index, value)
	return redis.String(reply, err)
}

func (p *Pool) LTrim(key string, start, stop int64) (string, error) {
	reply, err := p.do("ltrim", key, start, stop)
	return redis.String(reply, err)
}

func (p *Pool) RPop(key string) (string, error) {
	reply, err := p.do("rpop", key)
	return redis.String(reply, err)
}

func (p *Pool) RPopLPush(source, dest string) (string, error) {
	reply, err := p.do("rpoplpush", source, dest)
	return redis.String(reply, err)
}

func (p *Pool) RPush(key string, values ...interface{}) (int, error) {
	args := make([]interface{}, 1+len(values))
	args[0] = key
	for i := 0; i < len(values); i++ {
		args[i+1] = values[i]
	}
	reply, err := p.do("rpush", args...)
	return redis.Int(reply, err)
}

func (p *Pool) RPushX(key string, value interface{}) (int, error) {
	reply, err := p.do("rpushx", key, value)
	return redis.Int(reply, err)
}

// --------------------------------------------Set-----------------------------------------------

func (p *Pool) SAdd(key string, members ...interface{}) (int, error) {
	var args = make([]interface{}, 1+len(members))
	args[0] = key
	for i := 0; i < len(members); i++ {
		args[i+1] = members[i]
	}
	reply, err := p.do("sadd", args...)
	return redis.Int(reply, err)
}

func (p *Pool) SCard(key string) (int, error) {
	reply, err := p.do("scard", key)
	return redis.Int(reply, err)
}

func (p *Pool) SDiff(keys ...interface{}) ([]string, error) {
	reply, err := p.do("sdiff", keys...)
	return redis.Strings(reply, err)
}

func (p *Pool) SDiffStore(dest string, keys ...string) (int, error) {
	args := make([]interface{}, 1+len(keys))
	args[0] = dest
	for i := 0; i < len(keys); i++ {
		args[i+1] = keys[i]
	}
	reply, err := p.do("sdiffstore", args...)
	return redis.Int(reply, err)
}

func (p *Pool) SInter(keys ...interface{}) ([]string, error) {
	reply, err := p.do("sinter", keys...)
	return redis.Strings(reply, err)
}

func (p *Pool) SInterStore(dest string, keys ...string) (int, error) {
	args := make([]interface{}, 1+len(keys))
	args[0] = dest
	for i := 0; i < len(keys); i++ {
		args[i+1] = keys[i]
	}
	reply, err := p.do("sinterstore", args...)
	return redis.Int(reply, err)
}

func (p *Pool) SIsMember(key string, member interface{}) (bool, error) {
	reply, err := p.do("sismember", key, member)
	return redis.Bool(reply, err)
}

func (p *Pool) SMembers(key string) ([]string, error) {
	reply, err := p.do("smembers", key)
	return redis.Strings(reply, err)
}

func (p *Pool) SMove(source, dest string, member interface{}) (bool, error) {
	reply, err := p.do("smove", source, dest, member)
	return redis.Bool(reply, err)
}

func (p *Pool) SPop(key string) (string, error) {
	reply, err := p.do("spop", key)
	return redis.String(reply, err)
}

func (p *Pool) SPopN(key string, count int) ([]string, error) {
	reply, err := p.do("spop", key, count)
	return redis.Strings(reply, err)
}

func (p *Pool) SRandMember(key string) (string, error) {
	reply, err := p.do("srandmember", key)
	return redis.String(reply, err)
}

func (p *Pool) SRandMemberN(key string, count int) ([]string, error) {
	reply, err := p.do("srandmember", key, count)
	return redis.Strings(reply, err)
}

func (p *Pool) SRem(key string, members ...interface{}) (int, error) {
	args := make([]interface{}, 1+len(members))
	args[0] = key
	for i := 0; i < len(members); i++ {
		args[i+1] = members[i]
	}
	reply, err := p.do("srem", args...)
	return redis.Int(reply, err)
}

func (p *Pool) SUnion(keys ...interface{}) ([]string, error) {
	reply, err := p.do("sunion", keys...)
	return redis.Strings(reply, err)
}

func (p *Pool) SUnionStore(dest string, keys ...string) (int, error) {
	args := make([]interface{}, 1+len(keys))
	args[0] = dest
	for i := 0; i < len(keys); i++ {
		args[i+1] = keys[i]
	}
	reply, err := p.do("sunionstore", args...)
	return redis.Int(reply, err)
}

// -------------------------------------------Hash---------------------------------------------

func (p *Pool) HDel(key string, fields ...string) (int, error) {
	args := make([]interface{}, 1+len(fields))
	args[0] = key
	for i := 0; i < len(fields); i++ {
		args[i+1] = fields[i]
	}
	reply, err := p.do("hdel", args...)
	return redis.Int(reply, err)
}

func (p *Pool) HExists(key, field string) (bool, error) {
	reply, err := p.do("hexists", key, field)
	return redis.Bool(reply, err)
}

func (p *Pool) HGet(key, field string) (string, error) {
	reply, err := p.do("hget", key, field)
	return redis.String(reply, err)
}

func (p *Pool) HGetAll(key string) (map[string]string, error) {
	reply, err := p.do("hgetall", key)
	return redis.StringMap(reply, err)
}

func (p *Pool) HIncrBy(key, field string, incr int) (int, error) {
	reply, err := p.do("hincrby", key, field, incr)
	return redis.Int(reply, err)
}

func (p *Pool) HIncrByFloat(key, field string, incr float64) (float64, error) {
	reply, err := p.do("hincrbyfloat", key, field, incr)
	return redis.Float64(reply, err)
}

func (p *Pool) HKeys(key string) ([]string, error) {
	reply, err := p.do("hkeys", key)
	return redis.Strings(reply, err)
}

func (p *Pool) HLen(key string) (int, error) {
	reply, err := p.do("hlen", key)
	return redis.Int(reply, err)
}

func (p *Pool) HMGet(key string, fields ...string) ([]string, error) {
	args := make([]interface{}, 1+len(fields))
	args[0] = key
	for i := 0; i < len(fields); i++ {
		args[i+1] = fields[i]
	}
	reply, err := p.do("hmget", args...)
	return redis.Strings(reply, err)
}

func (p *Pool) HMSet(key string, fields map[string]interface{}) (string, error) {
	args := make([]interface{}, 1+len(fields)*2)
	args[0] = key
	i := 1
	for k, v := range fields {
		args[i] = k
		args[i+1] = v
		i += 2
	}
	reply, err := p.do("hmset", args...)
	return redis.String(reply, err)
}

func (p *Pool) HSet(key, field string, value interface{}) (bool, error) {
	reply, err := p.do("hset", key, field, value)
	return redis.Bool(reply, err)
}

func (p *Pool) HSetNX(key, field string, value interface{}) (string, error) {
	reply, err := p.do("hsetnx", key, field, value)
	return redis.String(reply, err)
}

func (p *Pool) HVals(key string) ([]string, error) {
	reply, err := p.do("hvals", key)
	return redis.Strings(reply, err)
}

// -------------------------------------------ZSet---------------------------------------------

// ZAdd 示例：zadd test_c score1 value1 score2 value2 [score value...]
func (p *Pool) ZAdd(key string, members ...interface{}) (int, error) {
	var args = make([]interface{}, len(members)+1)
	args[0] = key
	for i := 0; i < len(members); i++ {
		args[1+i] = members[i]
	}
	reply, err := p.do("zadd", args...)
	return redis.Int(reply, err)
}

func (p *Pool) ZIncr(key string, members ...interface{}) (int, error) {
	var args = make([]interface{}, len(members)+1)
	args[0] = key
	for i := 0; i < len(members); i++ {
		args[1+i] = members[i]
	}
	reply, err := p.do("zincr", args...)
	return redis.Int(reply, err)
}

func (p *Pool) ZIncrBy(key string, increment float64, members ...interface{}) (float64, error) {
	var args = make([]interface{}, len(members)+2)
	args[0] = key
	args[1] = increment
	for i := 0; i < len(members); i++ {
		args[2+i] = members[i]
	}
	reply, err := p.do("zincrby", args...)
	return redis.Float64(reply, err)
}

func (p *Pool) ZCard(key string) (int, error) {
	reply, err := p.do("zcard", key)
	return redis.Int(reply, err)
}

func (p *Pool) ZCount(key, min, max string) (int, error) {
	reply, err := p.do("zcount", key, min, max)
	return redis.Int(reply, err)
}

func (p *Pool) ZLexCount(key, min, max string) (int, error) {
	reply, err := p.do("zlexcount", key, min, max)
	return redis.Int(reply, err)
}

func (p *Pool) ZInterStore(dest string, keys ...string) (int, error) {
	var args = make([]interface{}, len(keys)+1)
	args[0] = dest
	for i := 0; i < len(keys); i++ {
		args[1+i] = keys[i]
	}
	reply, err := p.do("zinterstore", args...)
	return redis.Int(reply, err)
}

func (p *Pool) ZRange(key string, start, stop int) ([]string, error) {
	reply, err := p.do("zrange", key, start, stop)
	return redis.Strings(reply, err)
}

func (p *Pool) ZRangeWithScores(key string, start, stop int) ([]string, error) {
	reply, err := p.do("zrange", key, start, stop, "withscores")
	return redis.Strings(reply, err)
}

// ZRangeByScore 正常是双闭区间，可以传start = (1, stop= (5 控制为开区间，即 1< score < 5
func (p *Pool) ZRangeByScore(key string, start, stop interface{}) ([]string, error) {
	reply, err := p.do("zrangebyscore", key, start, stop)
	return redis.Strings(reply, err)
}

func (p *Pool) ZRangeByScoreWithScores(key string, start, stop interface{}) ([]string, error) {
	reply, err := p.do("zrangebyscore", key, start, stop, "withscores")
	return redis.Strings(reply, err)
}

// ZRank 返回member的索引位置
func (p *Pool) ZRank(key, member string) (int, error) {
	reply, err := p.do("zrank", key, member)
	return redis.Int(reply, err)
}

func (p *Pool) ZRem(key string, members ...string) (int, error) {
	args := make([]interface{}, 1+len(members))
	args[0] = key
	for i := 0; i < len(members); i++ {
		args[1+i] = members[i]
	}
	reply, err := p.do("zrem", args...)
	return redis.Int(reply, err)
}

func (p *Pool) ZRemRangeByRank(key string, start, stop int) (int, error) {
	reply, err := p.do("zremrangebyrank", key, start, stop)
	return redis.Int(reply, err)
}

func (p *Pool) ZRemRangeByScore(key, min, max interface{}) (int, error) {
	reply, err := p.do("zremrangebyscore", key, min, max)
	return redis.Int(reply, err)
}

func (p *Pool) ZRemRangeByLex(key, min, max string) (int, error) {
	reply, err := p.do("zremrangebylex", key, min, max)
	return redis.Int(reply, err)
}

func (p *Pool) ZRevRange(key string, start, stop int) ([]string, error) {
	reply, err := p.do("zrevrange", key, start, stop)
	return redis.Strings(reply, err)
}

func (p *Pool) ZRevRangeWithScores(key string, start, stop int) ([]string, error) {
	reply, err := p.do("zrevrange", key, start, stop, "withscores")
	return redis.Strings(reply, err)
}

func (p *Pool) ZRevRangeByScore(key string, limitOpt ...interface{}) ([]string, error) {
	args := make([]interface{}, 1+len(limitOpt))
	args[0] = key
	for i := 0; i < len(limitOpt); i++ {
		args[1+i] = limitOpt[i]
	}
	reply, err := p.do("zrevrangebyscore", limitOpt...)
	return redis.Strings(reply, err)
}

func (p *Pool) ZRevRank(key, member string) (int, error) {
	reply, err := p.do("zrevrank", key, member)
	return redis.Int(reply, err)
}

func (p *Pool) ZScore(key, member string) (float64, error) {
	reply, err := p.do("zscore", key, member)
	return redis.Float64(reply, err)
}

func (p *Pool) ZUnionStore(dest string, keys ...string) (int, error) {
	args := make([]interface{}, 2+len(keys))

	args[0] = dest
	args[1] = len(keys)
	for i := 0; i < len(keys); i++ {
		args[2+i] = keys[i]
	}

	reply, err := p.do("zunionstore", args...)
	return redis.Int(reply, err)
}

// ---------------------------------------------------GEO-----------------------------------------------------

// GeoAdd 示例：GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
func (p *Pool) GeoAdd(key string, geoLocationAndKey ...interface{}) (int, error) {
	args := make([]interface{}, 1+len(geoLocationAndKey))
	args[0] = key
	for i := 0; i < len(geoLocationAndKey); i++ {
		args[1+i] = geoLocationAndKey[i]
	}
	reply, err := p.do("geoadd", args...)
	return redis.Int(reply, err)
}

// GeoRadius 以给定的经纬度为中心， 返回键包含的位置成员当中， 与中心的距离不超过给定最大距离的所有位置元素
// 示例：GEORADIUS Sicily 15 37 200 km WITHDIST
func (p *Pool) GeoRadius(key string, longitude, latitude float64, radius int, unit string) ([]string, error) {
	reply, err := p.do("georadius", key, longitude, latitude, radius, unit)
	return redis.Strings(reply, err)
}

func (p *Pool) GeoRadiusWithDist(key string, longitude float64, latitude float64, radius int, unit string, orderType string) ([][]string, error) {
	reply, err := p.do("georadius", key, longitude, latitude, radius, unit, "withdist", orderType)
	if err != nil {
		return nil, err
	}
	var res [][]string
	if _, ok := reply.([]interface{}); !ok {
		return res, err
	}
	var pointList = reply.([]interface{})
	for _, v := range pointList {
		if _, ok := v.([]interface{}); !ok {
			continue
		}
		sub := v.([]interface{})
		// 再将sub[0]和sub[1]转为string
		key := string(sub[0].([]uint8))
		distance := string(sub[1].([]uint8))
		res = append(res, []string{key, distance})
	}

	return res, nil
}

func (p *Pool) GeoRadiusWithCoord(key string, longitude float64, latitude float64, radius int, unit string, orderType string) ([][]string, error) {
	reply, err := p.do("georadius", key, longitude, latitude, radius, unit, "withcoord", orderType)
	if err != nil {
		return nil, err
	}
	var res [][]string
	if _, ok := reply.([]interface{}); !ok {
		return res, err
	}
	var pointList = reply.([]interface{})
	var resLongitude, resLatitude string
	for _, v := range pointList {
		if _, ok := v.([]interface{}); !ok {
			continue
		}
		var subInfo = v.([]interface{})
		if len(subInfo) < 2 {
			continue
		}
		var subSlice = make([]string, 0)

		subSlice = append(subSlice, string(subInfo[0].([]uint8)))

		var subDist = subInfo[1].([]interface{})
		resLongitude = string(subDist[0].([]uint8))
		resLatitude = string(subDist[1].([]uint8))
		subSlice = append(subSlice, resLongitude, resLatitude)

		res = append(res, subSlice)
	}

	return res, nil
}

// GeoRadiusByMember 以给定的成员为中心， 返回键包含的位置元素当中，与中心的距离不超过给定最大距离的所有位置元素
// 示例：GEORADIUSBYMEMBER Sicily Agrigento 100 km
func (p *Pool) GeoRadiusByMember(key, member string, queryOpt ...interface{}) ([]string, error) {
	args := make([]interface{}, 2+len(queryOpt))
	args[0] = key
	args[1] = member
	for i := 0; i < len(queryOpt); i++ {
		args[2+i] = queryOpt[i]
	}
	reply, err := p.do("georadiusbymember", args...)
	return redis.Strings(reply, err)
}

// GeoDist 返回两个给定位置的成员之间的距离
// 示例：GEODIST Sicily Palermo Catania km
func (p *Pool) GeoDist(key string, member1, member2, unit string) (float64, error) {
	if unit == "" {
		unit = "km"
	}
	reply, err := p.do("geodist", key, member1, member2, unit)
	return redis.Float64(reply, err)
}

// GeoHash 返回一个或多个成员的geohash表示
func (p *Pool) GeoHash(key string, members ...string) ([]string, error) {
	args := make([]interface{}, 1+len(members))
	args[0] = key
	for i := 0; i < len(members); i++ {
		args[1+i] = members[i]
	}
	reply, err := p.do("geohash", args...)
	return redis.Strings(reply, err)
}

// GeoPos 获取指定成员的经纬度
func (p *Pool) GeoPos(key string, members ...string) ([]string, error) {
	args := make([]interface{}, 1+len(members))
	args[0] = key
	for i := 0; i < len(members); i++ {
		args[1+i] = members[i]
	}
	reply, err := p.do("geopos", args...)
	return redis.Strings(reply, err)
}

// -------------------------------------------BitMap---------------------------------------------

func (p *Pool) GetBit(key string, offset int) (int, error) {
	reply, err := p.do("getbit", key, offset)
	return redis.Int(reply, err)
}

func (p *Pool) SetBit(key string, offset int, bit int) (int, error) {
	reply, err := p.do("setbit", key, offset, bit)
	return redis.Int(reply, err)
}

// BitCount 统计value中被置为1的数量，可以通过指定start、end让计数只在特定的位上进行
func (p *Pool) BitCount(key string, queryOpt ...interface{}) (int, error) {
	args := make([]interface{}, 1+len(queryOpt))
	args[0] = key
	for i := 0; i < len(queryOpt); i++ {
		args[1+i] = queryOpt[i]
	}
	reply, err := p.do("bitcount", args...)
	return redis.Int(reply, err)
}

// BitOp 对一个或多个bitmap，进行与、或、非、异或运算，并将结果保存在dest中。op可以为and、or、not、xor
func (p *Pool) BitOp(op, dest string, keys ...string) (int, error) {
	args := make([]interface{}, 2+len(keys))
	args[0] = op
	args[1] = dest
	for i := 0; i < len(keys); i++ {
		args[2+i] = keys[i]
	}
	reply, err := p.do("bitop", args...)
	return redis.Int(reply, err)
}

// BitPos 返回Bitmap中第一个值为bit的位置，可以通过传start、end位置控制查询范围
func (p *Pool) BitPos(key string, bit int, pos ...int) (int, error) {
	args := make([]interface{}, 2+len(pos))
	args[0] = key
	args[1] = bit
	switch len(pos) {
	case 0:
	case 1:
		args[2] = pos[0]
	case 2:
		args[2] = pos[0]
		args[3] = pos[1]
	default:
		args[2] = pos[0]
		args[3] = pos[1]
	}
	reply, err := p.do("bitop", args...)
	return redis.Int(reply, err)
}

// -------------------------------------------布隆过滤器Bloom---------------------------------------------

// BfAdd 向布隆过滤器中添加一个元素
func (p *Pool) BfAdd(key string, item string) (bool, error) {
	reply, err := p.do("bf.add", key, item)
	return redis.Bool(reply, err)
}

// BfMAdd 向布隆过滤器中添加多个元素
func (p *Pool) BfMAdd(key string, items []string) ([]int64, error) {
	args := redis.Args{key}.AddFlat(items)
	reply, err := p.do("bf.madd", args...)
	return redis.Int64s(reply, err)
}

// BfExists 检查一个元素是否存在于布隆过滤器中
func (p *Pool) BfExists(key string, item string) (bool, error) {
	reply, err := p.do("bf.exists", key, item)
	return redis.Bool(reply, err)
}

// BfMExists 检查多个元素是否存在于布隆过滤器中
func (p *Pool) BfMExists(key string, items []string) ([]int64, error) {
	args := redis.Args{key}.AddFlat(items)
	reply, err := p.do("bf.mexists", args...)
	return redis.Int64s(reply, err)
}

// BfInfo 获取布隆过滤器的信息，包括容量、误判率等。
func (p *Pool) BfInfo(key string) (info map[string]int64, err error) {
	result, err := p.do("bf.info", key)
	if err != nil {
		return nil, err
	}
	values, err := redis.Values(result, nil)
	if err != nil {
		return nil, err
	}
	if len(values)%2 != 0 {
		return nil, errors.New("Info expects even number of values result")
	}
	info = map[string]int64{}
	for i := 0; i < len(values); i += 2 {
		key, err = redis.String(values[i], nil)
		if err != nil {
			return nil, err
		}
		info[key], err = redis.Int64(values[i+1], nil)
		if err != nil {
			return nil, err
		}
	}
	return info, nil
}

// BfReserve  创建一个新的布隆过滤器，并指定容量和误判率
func (p *Pool) BfReserve(key string, errorRate float64, capacity uint64) error {
	_, err := p.do("bf.reserve", key,
		strconv.FormatFloat(errorRate, 'g', 16, 64),
		capacity)
	return err
}
